package com.fpt.edu.vn.h2tv.dao;

import java.util.List;
import java.util.logging.Level;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.eclipse.persistence.config.HintValues;
import org.eclipse.persistence.config.QueryHints;

import com.fpt.edu.vn.h2tv.dao.entity.TbAccount;

/**
 * A data access object (DAO) providing persistence and search support for
 * TbAccount entities. Transaction control of the save(), update() and delete()
 * operations must be handled externally by senders of these methods or must be
 * manually added to each of these methods for data to be persisted to the JPA
 * datastore.
 * 
 * @see com.fpt.edu.vn.h2tv.dao.entity.TbAccount
 * @author MyEclipse Persistence Tools
 */

public class TbAccountDAO implements ITbAccountDAO {
	// property constants
	public static final String USERNAME = "username";
	public static final String PASSWORD = "password";
	public static final String VERTIFICATIONPASSWORD = "vertificationpassword";
	public static final String FIRSTNAME = "firstname";
	public static final String LASTNAME = "lastname";
	public static final String PHONENUMBER = "phonenumber";
	public static final String ADDRESS = "address";
	public static final String ROLE = "role";

	private EntityManager getEntityManager() {
		return EntityManagerHelper.getEntityManager();
	}

	/**
	 * Perform an initial save of a previously unsaved TbAccount entity. All
	 * subsequent persist actions of this entity should use the #update()
	 * method. This operation must be performed within the a database
	 * transaction context for the entity's data to be permanently saved to the
	 * persistence store, i.e., database. This method uses the
	 * {@link javax.persistence.EntityManager#persist(Object)
	 * EntityManager#persist} operation.
	 * 
	 * <pre>
	 * EntityManagerHelper.beginTransaction();
	 * TbAccountDAO.save(entity);
	 * EntityManagerHelper.commit();
	 * </pre>
	 * 
	 * @param entity
	 *            TbAccount entity to persist
	 * @throws RuntimeException
	 *             when the operation fails
	 */
	public void save(TbAccount entity) {
		EntityManagerHelper.log("saving TbAccount instance", Level.INFO, null);
		try {
			getEntityManager().persist(entity);
			EntityManagerHelper.log("save successful", Level.INFO, null);
		} catch (RuntimeException re) {
			EntityManagerHelper.log("save failed", Level.SEVERE, re);
			throw re;
		}
	}

	/**
	 * Delete a persistent TbAccount entity. This operation must be performed
	 * within the a database transaction context for the entity's data to be
	 * permanently deleted from the persistence store, i.e., database. This
	 * method uses the {@link javax.persistence.EntityManager#remove(Object)
	 * EntityManager#delete} operation.
	 * 
	 * <pre>
	 * EntityManagerHelper.beginTransaction();
	 * TbAccountDAO.delete(entity);
	 * EntityManagerHelper.commit();
	 * entity = null;
	 * </pre>
	 * 
	 * @param entity
	 *            TbAccount entity to delete
	 * @throws RuntimeException
	 *             when the operation fails
	 */
	public void delete(TbAccount entity) {
		EntityManagerHelper
				.log("deleting TbAccount instance", Level.INFO, null);
		try {
			entity = getEntityManager().getReference(TbAccount.class,
					entity.getUserid());
			getEntityManager().remove(entity);
			EntityManagerHelper.log("delete successful", Level.INFO, null);
		} catch (RuntimeException re) {
			EntityManagerHelper.log("delete failed", Level.SEVERE, re);
			throw re;
		}
	}

	/**
	 * Persist a previously saved TbAccount entity and return it or a copy of it
	 * to the sender. A copy of the TbAccount entity parameter is returned when
	 * the JPA persistence mechanism has not previously been tracking the
	 * updated entity. This operation must be performed within the a database
	 * transaction context for the entity's data to be permanently saved to the
	 * persistence store, i.e., database. This method uses the
	 * {@link javax.persistence.EntityManager#merge(Object) EntityManager#merge}
	 * operation.
	 * 
	 * <pre>
	 * EntityManagerHelper.beginTransaction();
	 * entity = TbAccountDAO.update(entity);
	 * EntityManagerHelper.commit();
	 * </pre>
	 * 
	 * @param entity
	 *            TbAccount entity to update
	 * @return TbAccount the persisted TbAccount entity instance, may not be the
	 *         same
	 * @throws RuntimeException
	 *             if the operation fails
	 */
	public TbAccount update(TbAccount entity) {
		EntityManagerHelper
				.log("updating TbAccount instance", Level.INFO, null);
		try {
			TbAccount result = getEntityManager().merge(entity);
			EntityManagerHelper.log("update successful", Level.INFO, null);
			return result;
		} catch (RuntimeException re) {
			EntityManagerHelper.log("update failed", Level.SEVERE, re);
			throw re;
		}
	}

	public TbAccount findById(Long id) {
		EntityManagerHelper.log("finding TbAccount instance with id: " + id,
				Level.INFO, null);
		try {
			TbAccount instance = getEntityManager().find(TbAccount.class, id);
			return instance;
		} catch (RuntimeException re) {
			EntityManagerHelper.log("find failed", Level.SEVERE, re);
			throw re;
		}
	}

	/**
	 * Find all TbAccount entities with a specific property value.
	 * 
	 * @param propertyName
	 *            the name of the TbAccount property to query
	 * @param value
	 *            the property value to match
	 * @param rowStartIdxAndCount
	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
	 *            row index in the query result-set to begin collecting the
	 *            results. rowStartIdxAndCount[1] specifies the the maximum
	 *            number of results to return.
	 * @return List<TbAccount> found by query
	 */
	@SuppressWarnings("unchecked")
	public List<TbAccount> findByProperty(String propertyName,
			final Object value, final int... rowStartIdxAndCount) {
		EntityManagerHelper.log("finding TbAccount instance with property: "
				+ propertyName + ", value: " + value, Level.INFO, null);
		try {
			final String queryString = "select model from TbAccount model where model."
					+ propertyName + "= :propertyValue";
			Query query = getEntityManager().createQuery(queryString);
			query.setParameter("propertyValue", value);
			if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
				int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
				if (rowStartIdx > 0) {
					query.setFirstResult(rowStartIdx);
				}

				if (rowStartIdxAndCount.length > 1) {
					int rowCount = Math.max(0, rowStartIdxAndCount[1]);
					if (rowCount > 0) {
						query.setMaxResults(rowCount);
					}
				}
			}
			query.setHint(QueryHints.REFRESH, HintValues.TRUE);
			return query.getResultList();
		} catch (RuntimeException re) {
			EntityManagerHelper.log("find by property name failed",
					Level.SEVERE, re);
			throw re;
		}
	}

	public List<TbAccount> findByUsername(Object username,
			int... rowStartIdxAndCount) {
		return findByProperty(USERNAME, username, rowStartIdxAndCount);
	}

	public List<TbAccount> findByPassword(Object password,
			int... rowStartIdxAndCount) {
		return findByProperty(PASSWORD, password, rowStartIdxAndCount);
	}

	public List<TbAccount> findByVertificationpassword(
			Object vertificationpassword, int... rowStartIdxAndCount) {
		return findByProperty(VERTIFICATIONPASSWORD, vertificationpassword,
				rowStartIdxAndCount);
	}

	public List<TbAccount> findByFirstname(Object firstname,
			int... rowStartIdxAndCount) {
		return findByProperty(FIRSTNAME, firstname, rowStartIdxAndCount);
	}

	public List<TbAccount> findByLastname(Object lastname,
			int... rowStartIdxAndCount) {
		return findByProperty(LASTNAME, lastname, rowStartIdxAndCount);
	}

	public List<TbAccount> findByPhonenumber(Object phonenumber,
			int... rowStartIdxAndCount) {
		return findByProperty(PHONENUMBER, phonenumber, rowStartIdxAndCount);
	}

	public List<TbAccount> findByAddress(Object address,
			int... rowStartIdxAndCount) {
		return findByProperty(ADDRESS, address, rowStartIdxAndCount);
	}

	public List<TbAccount> findByRole(Object role, int... rowStartIdxAndCount) {
		return findByProperty(ROLE, role, rowStartIdxAndCount);
	}

	/**
	 * Find all TbAccount entities.
	 * 
	 * @param rowStartIdxAndCount
	 *            Optional int varargs. rowStartIdxAndCount[0] specifies the the
	 *            row index in the query result-set to begin collecting the
	 *            results. rowStartIdxAndCount[1] specifies the the maximum
	 *            count of results to return.
	 * @return List<TbAccount> all TbAccount entities
	 */
	@SuppressWarnings("unchecked")
	public List<TbAccount> findAll(final int... rowStartIdxAndCount) {
		EntityManagerHelper.log("finding all TbAccount instances", Level.INFO,
				null);
		try {
			final String queryString = "select model from TbAccount model";
			Query query = getEntityManager().createQuery(queryString);
			if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
				int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
				if (rowStartIdx > 0) {
					query.setFirstResult(rowStartIdx);
				}

				if (rowStartIdxAndCount.length > 1) {
					int rowCount = Math.max(0, rowStartIdxAndCount[1]);
					if (rowCount > 0) {
						query.setMaxResults(rowCount);
					}
				}
			}
			query.setHint(QueryHints.REFRESH, HintValues.TRUE);
			return query.getResultList();
		} catch (RuntimeException re) {
			EntityManagerHelper.log("find all failed", Level.SEVERE, re);
			throw re;
		}
	}

    public TbAccount getUserInfoByUserNamePassword(String userName, String password){
        String queryString = "select model from TbAccount model where model.username = :username and model.isBanned = false and model.password = :password";
        Query query = getEntityManager().createQuery(queryString);
        query.setParameter("username", userName);
        query.setParameter("password", password);
        try{
        return (TbAccount) query.getSingleResult();
        }catch(NoResultException ex){
            return null;
        }
        }
    
    @SuppressWarnings("unchecked")
    public List<TbAccount> findStaff(){
        String queryString = "SELECT * FROM tb_account where role = ?admin or role = ?staff";
        Query query = getEntityManager().createNativeQuery(queryString, TbAccount.class);
        query.setParameter("admin", "admin");
        query.setParameter("staff", "staff");
        query.setHint(QueryHints.REFRESH, HintValues.TRUE);
        return query.getResultList();
    }
    
    @SuppressWarnings("unchecked")
    public List<TbAccount> findCustomer(){
        String queryString = "SELECT * FROM tb_account where role = ?cus";
        Query query = getEntityManager().createNativeQuery(queryString, TbAccount.class);
        query.setParameter("cus", "customer"); 
        query.setHint(QueryHints.REFRESH, HintValues.TRUE);
        return query.getResultList();
    }
    
    @SuppressWarnings("unchecked")
    public List<TbAccount> findAllAdmin(){
        String queryString = "SELECT * FROM tb_account where role = ?ad";
        Query query = getEntityManager().createNativeQuery(queryString, TbAccount.class);
        query.setParameter("ad", "admin");   
        query.setHint(QueryHints.REFRESH, HintValues.TRUE);
        return query.getResultList();
    }
    
    @SuppressWarnings("unchecked")
    public List<TbAccount> findAllStaff(){
        String queryString = "SELECT * FROM tb_account where role = ?st";
        Query query = getEntityManager().createNativeQuery(queryString, TbAccount.class);
        query.setParameter("st", "staff");  
        query.setHint(QueryHints.REFRESH, HintValues.TRUE);
        return query.getResultList();
    }
    
    @SuppressWarnings("unchecked")
    public List<TbAccount> searchStaffByUsername(String username){
        String queryString = "SELECT * FROM tb_account where username like ?un and (role=?ad or role=?st)";
        Query query = getEntityManager().createNativeQuery(queryString, TbAccount.class);
        query.setParameter("un", "%"+username+"%");   
        query.setParameter("ad", "admin"); 
        query.setParameter("st", "staff"); 
        query.setHint(QueryHints.REFRESH, HintValues.TRUE);
        return query.getResultList();
    }
    
    @SuppressWarnings("unchecked")
    public List<TbAccount> searchCustomerByUsername(String username){
        String queryString = "SELECT * FROM tb_account where username like ?un and role=?cus";
        Query query = getEntityManager().createNativeQuery(queryString, TbAccount.class);
        query.setParameter("un", "%"+username+"%");   
        query.setParameter("cus", "customer");  
        query.setHint(QueryHints.REFRESH, HintValues.TRUE);
        return query.getResultList();
    }
}